package com.springark.ms.springarkgateway.filter;

import cn.hankchan.utils.JSONParseUtils;
import cn.hankchan.utils.UniqueUtils;
import com.springark.ms.commons.MsApiResult;
import com.springark.ms.commons.consts.SpringarkRequestHeaders;
import com.springark.ms.commons.consts.SpringarkRequestParameters;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 网关的 access_token 校验
 * @see <a href="https://cloud.spring.io/spring-cloud-gateway/single/spring-cloud-gateway.html#_global_filters">参考地址</a>
 * @author hankchan
 * @since 2019/5/9
 */
@Component
public class AccessTokenGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String requestId = UniqueUtils.getUUId() + "";
        String appId = exchange.getRequest().getHeaders().getFirst(SpringarkRequestHeaders.APP_ID);
        if(null == appId || appId.isEmpty()) {
            return returnCauseUnauthorized(exchange, "required request headers: app_id", requestId);
        }
        String accessToken = exchange.getRequest().getQueryParams().getFirst(SpringarkRequestParameters.ACCESS_TOKEN);
        if(null == accessToken || accessToken.isEmpty()) {
            return returnCauseUnauthorized(exchange, "required request parameters: access_token", requestId);
        }
        // TODO 后续加入 access_token 校验
        // 如果是写入 request header 那就需要经过 chain 的处理
        ServerHttpRequest request = exchange.getRequest().mutate().header(SpringarkRequestHeaders.REQUEST_ID, requestId).build();
        return chain.filter(exchange.mutate().request(request).build());
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private Mono<Void> returnCauseUnauthorized(ServerWebExchange exchange, String msg, String requestId) {
        // 返回未授权的HTTP状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        // 自定义响应结构的返回方式
        String body = JSONParseUtils.object2JsonString(MsApiResult.newInstance()
                .error((long) HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase() + ":" + msg, requestId));
        DataBuffer dataBuffer = exchange.getResponse().bufferFactory().wrap(body.getBytes(StandardCharsets.UTF_8));
        return exchange.getResponse().writeWith(Flux.just(dataBuffer));
    }
}
